#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>

#include "core.h"
#include "ex.h"
#include "reg.h"
#include "../bus/xbar.h"

static core_t core;
static volatile uint32_t pc;

static uint32_t get_pc();
static void set_pc(uint32_t val);
static uint32_t fetch_instr();
static void exec_instr(uint32_t instr);
static uint32_t get_gpr_reg(uint32_t idx);
static void set_gpr_reg(uint32_t idx, uint32_t val);
static uint32_t get_csr_reg(uint32_t idx);
static void set_csr_reg(uint32_t idx, uint32_t val);


core_t *core_init(uint32_t reset_pc)
{
    pc = reset_pc;

    core.get_pc = get_pc;
    core.set_pc = set_pc;
    core.fetch_instr = fetch_instr;
    core.exec_instr = exec_instr;
    core.get_gpr_reg = get_gpr_reg;
    core.set_gpr_reg = set_gpr_reg;
    core.get_csr_reg = get_csr_reg;
    core.set_csr_reg = set_csr_reg;

    return (&core);
}

uint32_t core_get_pc()
{
    return pc;
}

static uint32_t get_pc()
{
    return pc;
}

void core_set_pc(uint32_t val)
{
    pc = val;
}

static void set_pc(uint32_t val)
{
    pc = val;
}

static uint32_t fetch_instr()
{
    uint32_t instr;

    instr = xbar_master_read(pc);

    return instr;
}

static void exec_instr(uint32_t instr)
{
    instr_decode_and_exec(instr);
}

static uint32_t get_gpr_reg(uint32_t idx)
{
    return reg_gpr_get(idx);
}

static void set_gpr_reg(uint32_t idx, uint32_t val)
{
    reg_gpr_set(idx, val);
}

static uint32_t get_csr_reg(uint32_t idx)
{
    return reg_csr_get(idx);
}

static void set_csr_reg(uint32_t idx, uint32_t val)
{
    reg_csr_set(idx, val);
}
